#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "Mutex.h"
#include "thread_encapsulation.h"

// 用c语言完成线程的封装

int tickets = 10000;
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 这个在全局定义一个锁，就不用像第一种方法区定义，初始化，释放锁了

void *Thread_run(void *args)
{
    while (1)
    {
        printf("我是一个新线程，我正在做： %s\n", args);
        sleep(1);
    }
}

// void *getTicket(void *args)
// {
//     while (1)
//     {
//         if (tickets > 0)
//         {
//             usleep(122);
//             printf("%s 正在进程抢票： %d\n", args, tickets--);
//         }
//         else
//         {
//             break;
//         }
//     }
//     return NULL;
// }

// int main()
// {
//     // 创建线程示例
//     Thread *my_thread1 = Thread_create(getTicket, (void *)"hellothread", 1);
//     Thread *my_thread2 = Thread_create(getTicket, (void *)"countthread", 2);
//     Thread *my_thread3 = Thread_create(getTicket, (void *)"logthread", 3);
//     Thread *my_thread4 = Thread_create(getTicket, (void *)"parkhread", 4);

//     // 等待线程结束
//     Thread_join(my_thread1);
//     Thread_join(my_thread2);
//     Thread_join(my_thread3);
//     Thread_join(my_thread4);

//     // 销毁线程结构体
//     Thread_destroy(my_thread1);
//     Thread_destroy(my_thread2);
//     Thread_destroy(my_thread3);
//     Thread_destroy(my_thread4);

//     return 0;
// }

// ---------------------   加锁 --------------------------

// 1. 如何看待锁
//    a.锁，本身就是一个共享资源！全局的变量是要被保护的，锁是用来保护全局资源的，锁本身也是全局资源，锁的安全是谁来保护呢？
//    b. pthread_mutex_lock，pthread_mutex_lock： 加锁的过程必须是安全的！ 加锁的过程是原子的！
//    c. 锁如果申请成功，就继续向后执行，如果申请暂时没有成功，执行流就会阻塞！
//    d. 谁持有锁，谁进入临界区!
// 2. 如何理解加锁解锁 --- 加锁的过程是原子的
// 3. 如果我们想简单的使用，该如何进行封装设计

// 把这个锁放到结构体里面，传给线程
typedef struct ThreadData
{
    char threadname[1024];
    pthread_mutex_t *mutex_p;
} ThreadData;

void *getTicket(void *args)
{
    ThreadData *td = (ThreadData *)args;
    while (1)
    {
        // 加锁和解锁的过程是多个线程串行执行的，所以程序变慢了。
        // 锁只规定互斥访问，没有规定必须谁先执行
        // 锁就是真的让多个执行流进行竞争的结果
        pthread_mutex_lock(td->mutex_p);
        if (tickets > 0)
        {
            usleep(122);
            printf("%s 正在进程抢票： %d\n", td->threadname, tickets--);
            pthread_mutex_unlock(td->mutex_p);
        }
        else
        {
            pthread_mutex_unlock(td->mutex_p);
            break;
        }
        // 抢完票之后就完了吗？ 当然不是
        // 这里模拟抢完票之后的流程
        usleep(1000);
    }
    return NULL;
}

int main()
{
    // 定义一个数组存放线程id
    pthread_t *pthread_arr = malloc(4 * sizeof(pthread_t));
    // 定义一把锁
    pthread_mutex_t lock;
    // 初始化这把锁
    pthread_mutex_init(&lock, NULL);
    // 怎么把这个锁传给线程呢？  定义一个结构体传进去
    for (int i = 0; i < 4; i++)
    {
        ThreadData *td = malloc(sizeof(ThreadData));
        char buffer[64];
        snprintf(buffer, sizeof(buffer), "thread %d", i);
        strcpy(td->threadname, buffer);
        td->mutex_p = &lock;
        // 创建线程
        pthread_create(&(*(pthread_arr + i)), NULL, getTicket, td);
    }

    // 等待线程
    for (int i = 0; i < 4; i++)
    {
        pthread_join(*(pthread_arr + i), NULL);
    }

    // pthread_t t1, t2, t3, t4;
    // pthread_create(&t1, NULL, getTicket, (void *)"thread 1");
    // pthread_create(&t2, NULL, getTicket, (void *)"thread 2");
    // pthread_create(&t3, NULL, getTicket, (void *)"thread 3");
    // pthread_create(&t4, NULL, getTicket, (void *)"thread 4");

    // 主线程
    // 等待线程
    // pthread_join(t1, NULL);
    // pthread_join(t2, NULL);
    // pthread_join(t3, NULL);
    // pthread_join(t4, NULL);

    // 锁不用了就释放
    pthread_mutex_destroy(&lock);
}
